package org.common.utils.id;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Date;

/**
 * 高性能全局唯一ID生成器
 * 20+年生命周期，32768个服务器ID，每毫秒512个序列
 * @author zhouzhibing
 * @date 2025/10/24 14:16
 */
public class IdGenerator {
    // 起始时间戳 (2024-01-01 00:00:00)
    private static final long START_TIMESTAMP = 1735660800000L;

    // 位数分配：时间戳(40位) + 服务器ID(15位) + 序列号(9位) = 64位
    private static final int SERVER_ID_BITS = 15;     // 32768个服务器
    private static final int SEQUENCE_BITS = 9;       // 每毫秒512个序列
    private static final int TIMESTAMP_BITS = 40;     // 约34.8年

    // 最大值
    private static final long MAX_SERVER_ID = (1L << SERVER_ID_BITS) - 1;
    private static final long MAX_SEQUENCE = (1L << SEQUENCE_BITS) - 1;

    // 位移
    private static final int SERVER_ID_SHIFT = SEQUENCE_BITS;
    private static final int TIMESTAMP_SHIFT = SERVER_ID_BITS + SEQUENCE_BITS;

    private final long serverId;
    private final AtomicLong state = new AtomicLong(0);

    public IdGenerator(long serverId) {
        if (serverId < 0 || serverId > MAX_SERVER_ID) {
            throw new IllegalArgumentException("服务器ID范围: 0-" + MAX_SERVER_ID);
        }
        this.serverId = serverId;
    }

    public long nextId() {
        while (true) {
            long current = state.get();
            long lastTime = current >>> SEQUENCE_BITS;
            long sequence = current & MAX_SEQUENCE;

            long now = System.currentTimeMillis();

            if (now < lastTime) {
                throw new RuntimeException("时钟回拨");
            }

            long newSequence;
            if (now == lastTime) {
                newSequence = (sequence + 1) & MAX_SEQUENCE;
                if (newSequence == 0) {
                    now = waitNextMillis(lastTime);
                }
            } else {
                newSequence = 0;
            }

            long newState = (now << SEQUENCE_BITS) | newSequence;

            if (state.compareAndSet(current, newState)) {
                long timestamp = now - START_TIMESTAMP;
                return (timestamp << TIMESTAMP_SHIFT)
                        | (serverId << SERVER_ID_SHIFT)
                        | newSequence;
            }
        }
    }

    private long waitNextMillis(long lastTime) {
        long now;
        do {
            now = System.currentTimeMillis();
        } while (now <= lastTime);
        return now;
    }

    // ==================== 解析工具方法 ====================

    public static long parseTimestamp(long id) {
        return (id >>> TIMESTAMP_SHIFT) + START_TIMESTAMP;
    }

    public static long parseServerId(long id) {
        return (id >>> SERVER_ID_SHIFT) & MAX_SERVER_ID;
    }

    public static long parseSequence(long id) {
        return id & MAX_SEQUENCE;
    }

    public static Date parseCreateTime(long id) {
        return new Date(parseTimestamp(id));
    }

    public static String formatIdInfo(long id) {
        return String.format("ID: %d, 服务器: %d, 序列号: %d, 创建时间: %tF %<tT",
                id, parseServerId(id), parseSequence(id), parseCreateTime(id));
    }

    public static boolean isValid(long id) {
        try {
            long serverId = parseServerId(id);
            long sequence = parseSequence(id);
            long timestamp = parseTimestamp(id);

            return serverId <= MAX_SERVER_ID &&
                    sequence <= MAX_SEQUENCE &&
                    timestamp >= START_TIMESTAMP &&
                    timestamp <= System.currentTimeMillis();
        } catch (Exception e) {
            return false;
        }
    }

    public static long getMaxServerId() {
        return MAX_SERVER_ID;
    }

    public static long getSequenceCapacity() {
        return MAX_SEQUENCE + 1;
    }

    public static Date getExpireTime() {
        return new Date(START_TIMESTAMP + (1L << TIMESTAMP_BITS));
    }
}